/****************************************************************************
 * Copyright (c) 2024 Qualcomm Technologies International, Ltd.
****************************************************************************/
/**
 * \file     task_mgr_wrapper.c
 * \ingroup  operators
 *
 *  Basic passthrough operator
 *
 */
 
#ifdef INSTALL_SUB_TASK_API /* Entire file is guarded for x2p compilation */ 

/****************************************************************************
Include Files
*/
#include "capabilities.h"
#include "../../components/sched_oxygen/sched_oxygen.h"
#include "task_mgr_wrapper.h"
#include "dls_kymera_util_if.h"
#include "basic_passthrough_thread_struct.h"
#include "audio_log/audio_log.h"

/****************************************************************************
Private Constant Definitions
*/


/****************************************************************************
Private Type Definitions
*/

#define ENABLE_PRINTS_FOR_TASK_IN_MULTITHREAD   (1) /* Enable/disable prints in tasks (includes timer task) */
#define ENABLE_PRINTS_FOR_BGINT_IN_MULTITHREAD  (0) /* Enable/disable prints in background routine (currently disabled to avoid more prints) */
#define ENABLE_BASIC_PASSTHROUGH_TIMER_TASK     (1) /* Enable/disable logic in timer */


#if ENABLE_PRINTS_FOR_TASK_IN_MULTITHREAD
#define PRINT_MULTITHREAD_ENTRY_TIME(a,b,c) L2_DBG_MSG3("TASK_MGR_WRAPPER::: Entry to %s at time %u \t context->task_id = 0x%x", a, b, c);
#define PRINT_MULTITHREAD_EXIT_TIME(a,b,c)  L2_DBG_MSG3("TASK_MGR_WRAPPER::: Exit from %s at time %u, time consumed = %u", a, b, c);
#define PRINT_MULTITHREAD_TASK_RESULT(a,b)  { (void)(a);(void)(b); }
#else
/* voids are to keep compiler quiet */
#define PRINT_MULTITHREAD_ENTRY_TIME(a,b,c) { (void)(a);(void)(b);(void)(c); }
#define PRINT_MULTITHREAD_EXIT_TIME(a,b,c)  { (void)(a);(void)(b);(void)(c); }
#define PRINT_MULTITHREAD_TASK_RESULT(a,b)  { (void)(a);(void)(b); }
#endif

#if ENABLE_PRINTS_FOR_BGINT_IN_MULTITHREAD
#define PRINT_MULTITHREAD_BK_ENTRY_TIME(a,b,c) L2_DBG_MSG3("TASK_MGR_WRAPPER::: Entry to BKGRND %s at time %u \t context->task_id = 0x%x", a, b, c);
#define PRINT_MULTITHREAD_BK_EXIT_TIME(a,b,c)  L2_DBG_MSG3("TASK_MGR_WRAPPER::: Exit from BKGRND %s at time %u, time consumed = %u", a, b, c);
#define PRINT_MULTITHREAD_BK_TASK_RESULT(a,b)  { (void)(a);(void)(b); }
#else
/* voids are to keep compiler quiet */
#define PRINT_MULTITHREAD_BK_ENTRY_TIME(a,b,c) { (void)(a);(void)(b);(void)(c); }
#define PRINT_MULTITHREAD_BK_EXIT_TIME(a,b,c)  { (void)(a);(void)(b);(void)(c); }
#define PRINT_MULTITHREAD_BK_TASK_RESULT(a,b)  { (void)(a);(void)(b); }
#endif

void (*task_handler_func_list[SUB_TASK_MAX]) (void**) = {
                                                          task_mgr_task_handler0,
                                                          task_mgr_task_handler1,
                                                          task_mgr_task_handler2
                                                        };

void (*background_handler_func_list[SUB_TASK_MAX]) (void**) = {
                                                          task_mgr_background_handler0,
                                                          task_mgr_background_handler1,
                                                          task_mgr_background_handler2
                                                        };
#define MUTEX_CNT_0  0 /*This is to allow multiple mutex in future. AT the moment value is ignored in FW*/

static inline unsigned acquire_lock(unsigned index)
{

    bool retVal =  sched_preemp_lock_get(index);
    taskid current_task_id = get_current_task();
    L2_DBG_MSG1("acquired the lock current_task_id=0x%x",current_task_id);
	return (retVal);
}

/**
 * \brief Release the semaphore.
 */
static inline unsigned release_lock(unsigned index)
{
    taskid current_task_id = get_current_task();
    L2_DBG_MSG1("releasing the lock current_task_id=0x%x",current_task_id);
    return sched_preemp_lock_release(index);
}

void basic_passthrough_timer_task(void *msg)
{
    BASIC_PASSTHROUGH_OP_DATA *opx_data = (BASIC_PASSTHROUGH_OP_DATA *)(msg);
    SUBTASK_CONTEXT* my_task = NULL;
#if ENABLE_BASIC_PASSTHROUGH_TIMER_TASK
    AUDIO_LOG_STRING(string1, "basic_passthrough_timer_task");
    TIME entry_time = time_get_time();
    TIME exit_time = 0;

    PRINT_MULTITHREAD_ENTRY_TIME(string1, entry_time, 0);
    acquire_lock(MUTEX_CNT_0);
    int localResult = 0;
    for(int task_cnt =0 ; task_cnt < MAX_SUB_TASK; task_cnt++)
    {
        if(opx_data->subTaskID[task_cnt] != 0 )
        {            
            my_task = (SUBTASK_CONTEXT *)opx_data->sub_task_context;
            my_task->result++;
            localResult = my_task->result++;
        }
    }
    release_lock(MUTEX_CNT_0);
    PRINT_MULTITHREAD_TASK_RESULT(string1, localResult);
#endif
    TIME current_time = time_get_time();
    if (NULL != my_task)
    {
        opx_data->passThroughTimerTaskId = timer_schedule_event_at(current_time + 500 + (my_task->result%5000), basic_passthrough_timer_task, opx_data);
    }
    else
    {
        opx_data->passThroughTimerTaskId = timer_schedule_event_at(current_time + 500 , basic_passthrough_timer_task, opx_data);
    }
#if ENABLE_BASIC_PASSTHROUGH_TIMER_TASK 
    exit_time = time_get_time();
    PRINT_MULTITHREAD_EXIT_TIME(string1, exit_time, (exit_time - entry_time));
#endif
}

void task_mgr_task_handler0(void **msg_data)
{
    L2_DBG_MSG("\n\n");
    AUDIO_LOG_STRING(string1, "task_mgr_task_handler0");
    TIME entry_time = time_get_time();
    TIME exit_time = 0;
    BASIC_PASSTHROUGH_OP_DATA *opx_data = (BASIC_PASSTHROUGH_OP_DATA *)*msg_data;
    SUBTASK_CONTEXT* my_task = (SUBTASK_CONTEXT *)(opx_data->sub_task_context);
    PRINT_MULTITHREAD_ENTRY_TIME(string1, entry_time, opx_data->subTaskID[0]);
    uint16 MessageId;
    void *MessagePointer;
    L2_DBG_MSG2("TASK_MGR_WRAPPER::: Put message call TASK 0x%x -> TASK 0x%x", opx_data->subTaskID[0], opx_data->subTaskID[2]);
    put_message(opx_data->subTaskID[2], 0, NULL);
    acquire_lock(MUTEX_CNT_0);
    L2_DBG_MSG2("TASK_MGR_WRAPPER::: Put message call TASK 0x%x -> TASK 0x%x", opx_data->subTaskID[0], opx_data->subTaskID[2]);
    put_message(opx_data->subTaskID[2], 0, NULL);
    my_task->result++;
    release_lock(MUTEX_CNT_0);
    PRINT_MULTITHREAD_TASK_RESULT(string1, my_task->result);
    get_message(context->task_id, &MessageId, &MessagePointer);
    exit_time = time_get_time();
    PRINT_MULTITHREAD_EXIT_TIME(string1, exit_time, (exit_time - entry_time));
    L2_DBG_MSG("\n\n");
}

void task_mgr_task_handler1(void **msg_data)
{
    AUDIO_LOG_STRING(string1, "task_mgr_task_handler1");
    TIME entry_time = time_get_time();
    TIME exit_time = 0;
    BASIC_PASSTHROUGH_OP_DATA *opx_data = (BASIC_PASSTHROUGH_OP_DATA *)*msg_data;
    SUBTASK_CONTEXT* my_task = (SUBTASK_CONTEXT *)(opx_data->sub_task_context);
    PRINT_MULTITHREAD_ENTRY_TIME(string1, entry_time, opx_data->subTaskID[1]);
    uint16 MessageId;
    void *MessagePointer;
    acquire_lock(MUTEX_CNT_0);
    my_task->result++;
    release_lock(MUTEX_CNT_0);
    PRINT_MULTITHREAD_TASK_RESULT(string1, my_task->result);
    get_message(context->task_id, &MessageId, &MessagePointer);
    exit_time = time_get_time();
    PRINT_MULTITHREAD_EXIT_TIME(string1, exit_time, (exit_time - entry_time));
}

void task_mgr_task_handler2(void **msg_data)
{
    AUDIO_LOG_STRING(string1, "task_mgr_task_handler2");
    TIME entry_time = time_get_time();
    TIME exit_time = 0;
    BASIC_PASSTHROUGH_OP_DATA *opx_data = (BASIC_PASSTHROUGH_OP_DATA *)*msg_data;
    SUBTASK_CONTEXT* my_task = (SUBTASK_CONTEXT *)(opx_data->sub_task_context);
    PRINT_MULTITHREAD_ENTRY_TIME(string1, entry_time, opx_data->subTaskID[2]);
    uint16 MessageId;
    void *MessagePointer;
    acquire_lock(MUTEX_CNT_0);
    my_task->result++;
    release_lock(MUTEX_CNT_0);
    PRINT_MULTITHREAD_TASK_RESULT(string1, my_task->result);
    get_message(context->task_id, &MessageId, &MessagePointer);
    exit_time = time_get_time();
    PRINT_MULTITHREAD_EXIT_TIME(string1, exit_time, (exit_time - entry_time));
}

void task_mgr_background_handler0(void **msg_data)
{
    AUDIO_LOG_STRING(string1, "task_mgr_background_handler0");
    TIME entry_time = time_get_time();
    TIME exit_time = 0;
    BASIC_PASSTHROUGH_OP_DATA *opx_data = (BASIC_PASSTHROUGH_OP_DATA *)*msg_data;
    PRINT_MULTITHREAD_BK_ENTRY_TIME(string1, entry_time, opx_data->subTaskID[0]);
    SUBTASK_CONTEXT* my_task = (SUBTASK_CONTEXT *)(opx_data->sub_task_context);
    acquire_lock(MUTEX_CNT_0);
    my_task->result++;
    release_lock(MUTEX_CNT_0);
    PRINT_MULTITHREAD_BK_TASK_RESULT(string1, my_task->result);
    exit_time = time_get_time();
    PRINT_MULTITHREAD_BK_EXIT_TIME(string1, exit_time, (exit_time - entry_time));
}

void task_mgr_background_handler1(void **msg_data)
{
    AUDIO_LOG_STRING(string1, "task_mgr_background_handler1");
    TIME entry_time = time_get_time();
    TIME exit_time = 0;
    BASIC_PASSTHROUGH_OP_DATA *opx_data = (BASIC_PASSTHROUGH_OP_DATA *)*msg_data;
    PRINT_MULTITHREAD_BK_ENTRY_TIME(string1, entry_time, opx_data->subTaskID[1]);
    SUBTASK_CONTEXT* my_task = (SUBTASK_CONTEXT *)(opx_data->sub_task_context);
    acquire_lock(MUTEX_CNT_0);
    my_task->result++;
    release_lock(MUTEX_CNT_0);
    PRINT_MULTITHREAD_BK_TASK_RESULT(string1, my_task->result);
    exit_time = time_get_time();
    PRINT_MULTITHREAD_BK_EXIT_TIME(string1, exit_time, (exit_time - entry_time));
}

void task_mgr_background_handler2(void **msg_data)
{
    AUDIO_LOG_STRING(string1, "task_mgr_background_handler2");
    TIME entry_time = time_get_time();
    TIME exit_time = 0;
    BASIC_PASSTHROUGH_OP_DATA *opx_data = (BASIC_PASSTHROUGH_OP_DATA *)*msg_data;
    PRINT_MULTITHREAD_BK_ENTRY_TIME(string1, entry_time, opx_data->subTaskID[2]);
    SUBTASK_CONTEXT* my_task = (SUBTASK_CONTEXT *)(opx_data->sub_task_context);
    acquire_lock(MUTEX_CNT_0);
    my_task->result++;
    release_lock(MUTEX_CNT_0);
    PRINT_MULTITHREAD_BK_TASK_RESULT(string1, my_task->result);
    exit_time = time_get_time();
    PRINT_MULTITHREAD_BK_EXIT_TIME(string1, exit_time, (exit_time - entry_time));
}

taskid task_mgr_create_task(PRIORITY task_priority,
                            void *task_data,
                            SUB_TASKS sub_task_id)
{
    taskid local_taskid =0;
    if (SUB_TASK_MAX > sub_task_id)
    {
        local_taskid = create_task(task_priority,
                                   task_data,
                                   task_handler_func_list[sub_task_id],
                                   background_handler_func_list[sub_task_id]
                                   );
    }
    else
    {
        L2_DBG_MSG("Invalid sub task id\n");
    }

    return local_taskid;
}


#endif /* INSTALL_SUB_TASK_API */